package com.vhall.component.plugin.core.service;

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.vhall.component.entity.common.VssTokenVO;
import com.vhall.component.framework.common.constant.CommonConstant;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.constant.PaasCommonConstant;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * @author lsl
 * @since 2021/4/26
 */
@Slf4j
@Service
public class VssTokenService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @Value("${paas.apps.lite.appId}")
    public String appId;

    /**
     * 创建token
     *
     * @return token
     */
    public String create(Integer thirdPartyUserId) {
        //获取过期时间戳
        long expireTimestamp = LocalDateTime.now().plusDays(1).toEpochSecond(ZoneOffset.of("+8"));
        //获取现在时间戳
        long nowTimestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        //计算时间差值
        long expireTime = expireTimestamp - nowTimestamp;
        return setTokenPermit(appId, thirdPartyUserId, expireTime);

    }

    /**
     * 设置访问权限
     *
     * @param appId            app id
     * @param thirdPartyUserId user id
     * @param expireTime       expire time
     * @return token
     */
    private String setTokenPermit(String appId, Integer thirdPartyUserId, long expireTime) {
        expireTime = expireTime != 0 ? expireTime : 3600 * 24;
        String accessToken = createAccessToken(appId, thirdPartyUserId);
        LocalDateTime time = LocalDateTime.ofEpochSecond(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) + expireTime, 0, ZoneOffset.ofHours(8));
        VssTokenVO vssTokenVO = new VssTokenVO();
        vssTokenVO.setAppId(appId);
        vssTokenVO.setThirdPartyUserId(thirdPartyUserId);
        vssTokenVO.setExpireTime(time);
        redisTemplate.opsForValue().set(accessToken, JsonUtil.toJsonString(vssTokenVO), expireTime, TimeUnit.SECONDS);
        return accessToken;
    }

    /**
     * 生成TOKEN
     *
     * @param appId            appid
     * @param thirdPartyUserId user id
     * @return access token
     */
    private String createAccessToken(String appId, Integer thirdPartyUserId) {
        //加密
        String str = appId + thirdPartyUserId + LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        String md5Result = DigestUtils.md5DigestAsHex(str.getBytes());
        String substring = StringUtils.substring(md5Result, 8, 24);
        return RedisKey.TOKEN_PERMIT_PREFIX + appId + ":" + substring;
    }


    /**
     * 生成  vss_token 不是 pass那边的 token
     * 规则是   access:3edbc591:b4d67b18acecfd77
     *
     * @param accountId account id
     * @return token
     */
    public String createToken(long accountId) {
        String md5Uid = MD5.create().digestHex(appId + accountId + System.currentTimeMillis(), CommonConstant.UTF8);
        md5Uid = md5Uid.substring(8, 24);
        String vssToken = RedisKey.TOKEN_PERMIT_PREFIX + appId + RedisKey.TOKEN_PARTITION + md5Uid;
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstant.DATETIME_FORMAT);
        JSONObject obj = new JSONObject();
        obj.put(PaasCommonConstant.APP_ID_KEY, appId);
        obj.put(PaasCommonConstant.THIRD_PARTY_USER_ID_KEY, accountId);
        obj.put("expire_time", LocalDateTime.now().plusDays(1).format(formatter));
        String jsonStr = JSON.toJSONString(obj);
        redisTemplate.opsForValue().set(vssToken, jsonStr, 1, TimeUnit.DAYS);
        return vssToken;
    }


    public VssTokenVO getTokenInfo(String accessToken) {
        VssTokenVO vo = null;
        String token = redisTemplate.opsForValue().get(accessToken);
        if (StringUtils.isBlank(token)) {
            throw new BusinessException(BizErrorCode.AUTH_VSS_TOKEN_EXPIRE);
        }
        String tokenText = JSON.parse(token).toString();
        try {
            vo = JSONObject.parseObject(tokenText, VssTokenVO.class);
        } catch (Exception e) {
            log.error("获取vss_token信息失败:" + token, e);
        }
        return vo;
    }

}
